<template>
<div class="channel-container">
    <el-row :gutter="20">
        <!-- PC端左侧频道列表 -->
        <el-col :xs="24" :sm="24" :md="6" :lg="4" :xl="4" class="pc-only">
            <div class="channel-list">
                <h3>频道列表</h3>
                <el-menu :default-active="id" class="channel-menu" @select="handleChannelSelect">
                    <el-menu-item v-for="channel in channels" :key="channel.id" :index="channel.id + ''">
                        <i :class="channel.icon"></i>
                        <span>{{ channel.name }}</span>
                    </el-menu-item>
                </el-menu>
            </div>
        </el-col>

        <!-- 移动端水平滚动频道列表 -->
        <el-col :xs="24" :sm="24" :md="0" :lg="0" :xl="0" class="mobile-only">
            <div class="mobile-channel-list">
                <div class="mobile-channels-scroll" ref="channelsScroll">
                    <div v-for="channel in channels" :key="channel.id"
                        :class="['mobile-channel-item', id === channel.id + '' ? 'active' : '']"
                        @click="handleChannelSelect(channel.id + '')">
                        <i :class="channel.icon"></i>
                        <span>{{ channel.name }}</span>
                    </div>
                </div>
            </div>
        </el-col>

        <el-col :xs="24" :sm="24" :md="18" :lg="20" :xl="20">
            <div class="website-grid" ref="websiteGrid" @touchstart="handleTouchStart" @touchmove="handleTouchMove"
                @touchend="handleTouchEnd" :style="contentStyle">
                <h2 class="pc-only">{{ currentChannel ? currentChannel.name : "" }} 相关网站</h2>
                <el-row :gutter="20">
                    <!-- 添加加载状态 -->
                    <el-col :span="24" v-if="loading">
                        <div class="loading-container">
                            <el-skeleton :rows="5" animated />
                        </div>
                    </el-col>
                    <template v-else-if="filteredWebsites.length > 0">
                        <el-col :xs="12" :sm="12" :md="8" :lg="6" :xl="4" v-for="site in filteredWebsites"
                            :key="site.id">
                            <el-card class="website-card" shadow="hover">
                                <div class="website-icon">
                                    <el-image v-if="site.icon" :src="site.icon" :alt="site.name" lazy
                                        :preview-src-list="[]" fit="contain">
                                        <div slot="placeholder" class="image-placeholder">
                                            <el-skeleton-item variant="image" style="width: 50px; height: 50px" />
                                        </div>
                                        <div slot="error" class="image-error">
                                            <i class="el-icon-picture-outline"></i>
                                        </div>
                                    </el-image>
                                    <i class="el-icon-link" v-else></i>
                                </div>
                                <div class="website-info">
                                    <h3>{{ site.name }}</h3>
                                    <p>{{ site.description }}</p>
                                    <div class="button-container">
                                        <el-button type="primary" size="small" @click="openWebsite(site.url)">
                                            访问网站
                                        </el-button>
                                    </div>
                                </div>
                            </el-card>
                        </el-col>
                    </template>
                    <el-col :span="24" v-else class="channel-container">
                        <el-empty description="暂无相关网站"></el-empty>
                    </el-col>
                </el-row>
            </div>
        </el-col>
    </el-row>
</div>
</template>

<script>
import { getChannels, getWebsitesByChannel } from "@/api/index";

export default {
    name: "ChannelList",
    props: {
        // 可以通过props接收初始频道ID
        initialChannelId: {
            type: String,
            default: "0",
        },
    },
    data() {
        return {
            id: this.initialChannelId,
            channels: [],
            websitesByChannel: {},
            loading: false, // 添加loading状态
            touchStartX: 0,
            touchEndX: 0,
            touchMoveX: 0, // 记录移动中的位置
            swipeThreshold: 80, // 降低滑动阈值，使滑动更灵敏
            isAnimating: false, // 是否正在执行动画
            swipeDirection: null, // 滑动方向
            swipeProgress: 0, // 滑动进度，用于视觉反馈
        };
    },
    computed: {
        currentChannel() {
            return this.channels.find((channel) => channel.id + "" === this.id);
        },
        filteredWebsites() {
            return this.websitesByChannel[this.id] || [];
        },
        contentStyle() {
            // 根据滑动状态返回内容区域的样式
            return {
                transition: this.isAnimating ? 'transform 0.3s ease-out, opacity 0.3s ease-out' : '',
                transform: this.swipeDirection ? `translateX(${this.swipeDirection === 'left' ? '-' : ''}${this.swipeProgress * 20}px)` : '',
                opacity: this.swipeDirection ? 1 - this.swipeProgress * 0.2 : 1
            };
        },
    },
    created() {
        // 确保channelId始终有值
        this.id = this.initialChannelId || "0";
        // 获取频道列表
        this.fetchChannels();
        // 获取当前频道的网站列表
        this.fetchWebsites(this.id);
    },
    methods: {
        // 获取所有频道
        async fetchChannels() {
            try {
                const res = await getChannels();
                if (res && res.data) {
                    this.channels = res.data;
                }
            } catch (error) {
                console.error("获取频道列表失败:", error);
                // 使用默认数据作为备用
                this.channels = [{ id: 1, name: "推荐", icon: "el-icon-star-on" }];
            }
        },
        // 获取指定频道的网站列表
        async fetchWebsites(id) {
            // 设置加载状态
            this.loading = true;
            try {
                const res = await getWebsitesByChannel(id);
                if (res && res.data) {
                    // 使用Vue.set确保响应式
                    this.$set(this.websitesByChannel, id, res.data);
                }
            } catch (error) {
                console.error(`获取频道${id}的网站列表失败:`, error);
            } finally {
                // 无论成功失败都关闭加载状态
                setTimeout(() => {
                    this.loading = false;
                }, 300); // 添加短暂延迟，避免闪烁
            }
        },
        handleChannelSelect(index) {
            if (this.id === index) return; // 避免重复点击

            this.id = index;
            // 如果没有该频道的网站数据，则从服务器获取
            if (!this.websitesByChannel[index]) {
                this.fetchWebsites(index);
            } else {
                // 即使有缓存数据，也显示短暂的加载状态，保持一致的用户体验
                this.loading = true;
                setTimeout(() => {
                    this.loading = false;
                }, 200);
            }
            // 触发自定义事件，通知父组件频道已更改
            this.$emit("channel-change", index);

            // 让选中的标签居中显示
            this.$nextTick(() => {
                this.scrollActiveChannelToCenter();
            });
        },
        openWebsite(url) {
            window.open(url, "_blank");
        },
        // 提供一个方法让外部可以设置当前频道
        setChannel(id) {
            if (this.id === id) return; // 避免重复设置

            this.id = id;
            // 如果没有该频道的网站数据，则从服务器获取
            if (!this.websitesByChannel[id]) {
                this.fetchWebsites(id);
            } else {
                // 即使有缓存数据，也显示短暂的加载状态
                this.loading = true;
                setTimeout(() => {
                    this.loading = false;
                }, 200);
            }
        },
        // 让选中的标签居中显示
        scrollActiveChannelToCenter() {
            if (!this.$refs.channelsScroll) return;

            const scrollContainer = this.$refs.channelsScroll;
            const activeItem = scrollContainer.querySelector('.mobile-channel-item.active');

            if (!activeItem) return;

            // 计算需要滚动的位置，使活动项居中
            const containerWidth = scrollContainer.offsetWidth;
            const itemWidth = activeItem.offsetWidth;
            const itemLeft = activeItem.offsetLeft;

            // 计算滚动位置，使选中项居中
            const scrollLeft = itemLeft - (containerWidth / 2) + (itemWidth / 2);

            // 使用平滑滚动效果
            scrollContainer.scrollTo({
                left: scrollLeft,
                behavior: 'smooth'
            });
        },

        // 处理触摸开始事件
        handleTouchStart(event) {
            // 只在移动端处理滑动事件
            if (window.innerWidth > 768) return;

            this.touchStartX = event.touches[0].clientX;
            this.touchMoveX = event.touches[0].clientX;
            this.isAnimating = false;
            this.swipeDirection = null;
            this.swipeProgress = 0;
        },

        // 处理网站列表区域的触摸开始事件
        handleWebsiteGridTouchStart(event) {
            // 阻止事件冒泡，防止触发频道切换
            event.stopPropagation();
        },

        // 处理触摸移动事件
        handleTouchMove(event) {
            // 只在移动端处理滑动事件
            if (window.innerWidth > 768 || this.isAnimating) return;

            this.touchMoveX = event.touches[0].clientX;
            const diffX = this.touchMoveX - this.touchStartX;

            // 确定滑动方向
            if (diffX > 0) {
                this.swipeDirection = 'right';
            } else if (diffX < 0) {
                this.swipeDirection = 'left';
            }

            // 计算滑动进度，最大为1（100%）
            this.swipeProgress = Math.min(Math.abs(diffX) / this.swipeThreshold, 1);

            // 应用实时的视觉反馈
            if (Math.abs(diffX) > 10) { // 添加一个小阈值，避免轻微触摸也触发动画
                // 防止事件冒泡和默认行为，如页面滚动
                event.preventDefault();

                // 使用计算属性中的样式，而不是直接操作DOM
                // 这样可以让Vue的响应式系统处理渲染，提供更平滑的动画效果
                this.$refs.websiteGrid.style.transition = 'transform 0.05s ease-out';
                this.$refs.websiteGrid.style.transform = `translateX(${diffX * 0.3}px)`;
                this.$refs.websiteGrid.style.opacity = 1 - this.swipeProgress * 0.2;

                // 预加载下一个频道的数据，提高切换速度
                if (this.swipeProgress > 0.5) {
                    const currentIndex = this.channels.findIndex(channel => channel.id + '' === this.id);
                    if (currentIndex !== -1) {
                        let nextIndex;
                        if (this.swipeDirection === 'right' && currentIndex > 0) {
                            nextIndex = currentIndex - 1;
                        } else if (this.swipeDirection === 'left' && currentIndex < this.channels.length - 1) {
                            nextIndex = currentIndex + 1;
                        }

                        if (nextIndex !== undefined) {
                            const nextChannelId = this.channels[nextIndex].id + '';
                            if (!this.websitesByChannel[nextChannelId]) {
                                this.fetchWebsites(nextChannelId);
                            }
                        }
                    }
                }
            }
        },

        // 处理触摸结束事件
        handleTouchEnd() {
            // 只在移动端处理滑动事件
            if (window.innerWidth > 768 || this.isAnimating) return;

            this.touchEndX = this.touchMoveX;
            const diffX = this.touchEndX - this.touchStartX;

            // 设置过渡动画，使回弹或切换更平滑
            if (this.$refs.websiteGrid) {
                this.$refs.websiteGrid.style.transition = 'transform 0.3s ease-out, opacity 0.3s ease-out';
            }

            // 如果滑动距离超过阈值，切换频道
            if (Math.abs(diffX) > this.swipeThreshold) {
                this.isAnimating = true;

                // 找到当前频道的索引
                const currentIndex = this.channels.findIndex(channel => channel.id + '' === this.id);
                if (currentIndex === -1) return;

                // 根据滑动方向确定下一个频道
                let nextIndex;
                if (diffX > 0 && currentIndex > 0) {
                    // 向右滑动，切换到上一个频道
                    nextIndex = currentIndex - 1;
                } else if (diffX < 0 && currentIndex < this.channels.length - 1) {
                    // 向左滑动，切换到下一个频道
                    nextIndex = currentIndex + 1;
                } else {
                    // 已经是第一个或最后一个频道，或者滑动方向不明确
                    // 执行回弹动画
                    if (this.$refs.websiteGrid) {
                        this.$refs.websiteGrid.style.transform = '';
                        this.$refs.websiteGrid.style.opacity = '1';
                    }

                    // 重置状态
                    setTimeout(() => {
                        this.swipeDirection = null;
                        this.swipeProgress = 0;
                        this.isAnimating = false;
                    }, 300);
                    return;
                }

                // 应用退出动画
                if (this.$refs.websiteGrid) {
                    const exitTranslate = diffX > 0 ? '100%' : '-100%';
                    this.$refs.websiteGrid.style.transform = `translateX(${exitTranslate})`;
                    this.$refs.websiteGrid.style.opacity = '0.8';
                }

                // 延迟切换频道，让退出动画有时间执行
                setTimeout(() => {
                    // 切换到新频道
                    const nextChannelId = this.channels[nextIndex].id + '';
                    this.handleChannelSelect(nextChannelId);

                    // 应用进入动画
                    if (this.$refs.websiteGrid) {
                        this.$refs.websiteGrid.style.transform = `translateX(${diffX > 0 ? '-' : ''}100%)`;
                        this.$refs.websiteGrid.style.opacity = '0.8';

                        // 强制重绘
                        this.$refs.websiteGrid.offsetHeight;

                        // 设置进入动画
                        this.$refs.websiteGrid.style.transition = 'transform 0.3s ease-out, opacity 0.3s ease-out';
                        this.$refs.websiteGrid.style.transform = '';
                        this.$refs.websiteGrid.style.opacity = '1';
                    }

                    // 添加短暂延迟后重置动画状态
                    setTimeout(() => {
                        this.swipeDirection = null;
                        this.swipeProgress = 0;
                        this.isAnimating = false;

                        // 清除所有内联样式，回到CSS控制
                        if (this.$refs.websiteGrid) {
                            this.$refs.websiteGrid.style = '';
                        }
                    }, 300);
                }, 150);
            } else {
                // 滑动距离不够，执行回弹动画
                if (this.$refs.websiteGrid) {
                    this.$refs.websiteGrid.style.transform = '';
                    this.$refs.websiteGrid.style.opacity = '1';
                }

                // 重置状态
                setTimeout(() => {
                    this.swipeDirection = null;
                    this.swipeProgress = 0;
                }, 300);
            }
        }
    },
};
</script>

<style scoped>
.channel-container {
    padding: 20px;
    min-height: calc(100vh - 60px);
    /* 添加最小高度，减去header高度 */
    position: relative;
}

.channel-list {
    background-color: #ffffff;
    border-radius: 8px;
    padding: 20px;
    margin-bottom: 20px;
    border: 1px solid #ebeef5;
    position: sticky;
    top: 60px;
    /* Header的高度 */
    z-index: 900;
    /* 确保在其他内容之上，但在header之下 */
    max-height: calc(100vh - 80px);
    /* 减去header高度和一些间距 */
    overflow-y: auto;
    /* 内容过多时可滚动 */
}

.channel-list h3 {
    margin-top: 0;
    margin-bottom: 15px;
    font-size: 18px;
    color: #303133;
    font-weight: 600;
    padding-bottom: 10px;
    border-bottom: 1px solid #ebeef5;
}

.channel-menu {
    border-right: none;
    margin-top: 10px;
}

.el-menu-item {
    height: 50px;
    line-height: 50px;
    margin-bottom: 5px;
    border-radius: 6px;
    transition: all 0.3s;
}

.el-menu-item i {
    color: #909399;
    font-size: 18px;
    margin-right: 5px;
}

.el-menu-item span {
    font-size: 15px;
    font-weight: 500;
}

.el-menu-item:hover,
.el-menu-item:focus {
    background-color: #ecf5ff;
}

.el-menu-item.is-active {
    background-color: #ecf5ff;
    color: #409eff;
    border-left: 3px solid #409eff;
}

.el-menu-item.is-active i {
    color: #409eff;
}

.website-grid {
    margin-top: 20px;
    transition: transform 0.3s ease-out, opacity 0.3s ease-out;
    /* 添加过渡效果，包括透明度变化 */
    will-change: transform, opacity;
    /* 提示浏览器这些属性会变化，优化性能 */
    backface-visibility: hidden;
    /* 防止3D变换时的闪烁 */
    perspective: 1000;
    /* 增强3D效果 */
}

/* 加载状态容器 */
.loading-container {
    padding: 20px;
    background-color: #ffffff;
    border-radius: 8px;
}

.website-card {
    margin-bottom: 20px;
    height: 100%;
    min-height: 220px;
    display: flex;
    flex-direction: column;
    border: 1px solid #e0e0e0;
    border-radius: 6px;
    transition: all 0.3s ease;
}

.website-card:hover {
    border-color: #409eff;
}

.website-icon {
    text-align: center;
    margin-bottom: 10px;
    height: 50px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.website-icon .el-image {
    width: 50px;
    height: 50px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.image-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: #f5f7fa;
    border-radius: 4px;
}

.image-error {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #909399;
    font-size: 20px;
    background-color: #f5f7fa;
    border-radius: 4px;
}

.website-info {
    display: flex;
    flex-direction: column;
    flex: 1;
}

.website-info h3 {
    margin: 10px 0;
    font-size: 16px;
    height: 22px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.website-info p {
    color: #666;
    font-size: 14px;
    margin-bottom: 15px;
    height: 40px;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

.button-container {
    margin-top: auto;
    text-align: center;
}

/* 移动端水平滚动频道列表 */
.mobile-channel-list {
    background-color: #ffffff;
    border-radius: 8px;
    padding: 15px 0;
    position: sticky;
    z-index: 10;
}

.mobile-channels-scroll {
    display: flex;
    overflow-x: auto;
    white-space: nowrap;
    -webkit-overflow-scrolling: touch;
    padding: 0 15px;
    scrollbar-width: none;
    /* Firefox */
}

.mobile-channels-scroll::-webkit-scrollbar {
    display: none;
    /* Chrome, Safari */
}

.mobile-channel-item {
    display: inline-flex;
    align-items: center;
    padding: 8px 16px;
    border-radius: 20px;
    margin-right: 10px;
    background-color: #f5f7fa;
    color: #606266;
    font-size: 14px;
    transition: all 0.3s;
    cursor: pointer;
}

.mobile-channel-item i {
    margin-right: 5px;
    font-size: 16px;
}

.mobile-channel-item.active {
    background-color: #409eff;
    color: #ffffff;
}

.mobile-channel-item.pre-active {
    background-color: #66b1ff;
    color: #ffffff;
    transform: scale(1.05);
}

/* 添加滑动切换动画效果 */
.slide-left-enter-active,
.slide-left-leave-active,
.slide-right-enter-active,
.slide-right-leave-active {
    transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
    /* 使用更平滑的缓动函数 */
}

.slide-left-enter {
    transform: translateX(100%);
    opacity: 0.8;
}

.slide-left-leave-to {
    transform: translateX(-100%);
    opacity: 0.8;
}

.slide-right-enter {
    transform: translateX(-100%);
    opacity: 0.8;
}

.slide-right-leave-to {
    transform: translateX(100%);
    opacity: 0.8;
}

/* 添加滑动过程中的视觉反馈样式 */
.swiping-left {
    transform: translateX(-20px);
    opacity: 0.9;
    transition: transform 0.1s ease-out, opacity 0.1s ease-out;
}

.swiping-right {
    transform: translateX(20px);
    opacity: 0.9;
    transition: transform 0.1s ease-out, opacity 0.1s ease-out;
}

/* 移动端浮动操作按钮 */
.mobile-fab {
    position: fixed;
    right: 20px;
    bottom: 70px;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background-color: #409eff;
    color: #ffffff;
    display: none;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 900;
    transition: all 0.3s;
}

.mobile-fab i {
    font-size: 24px;
}

.mobile-fab:active {
    transform: scale(0.95);
}

/* 响应式设计 */
.pc-only {
    display: block;
}

.mobile-only {
    display: none;
}

/* 响应式样式 */
@media (max-width: 768px) {
    .channel-container {
        padding: 10px;
    }

    .pc-only {
        display: none;
    }

    .mobile-only {
        display: block;
    }

    .website-grid h2 {
        font-size: 18px;
        margin: 15px 0;
        padding-left: 10px;
    }

    .website-card {
        margin-bottom: 15px;
        min-height: 180px;
    }

    .website-info h3 {
        font-size: 15px;
        margin-top: 5px;
    }

    .website-info p {
        font-size: 13px;
        height: 36px;
    }

    .button-container .el-button {
        font-size: 12px;
        padding: 8px 15px;
    }

    .mobile-fab {
        display: flex;
    }
}

/* 超小屏幕优化 */
@media (max-width: 480px) {
    .channel-container {
        padding: 8px;
    }

    .mobile-channel-list {
        padding: 10px 0;
    }

    .mobile-channel-item {
        padding: 6px 12px;
        font-size: 13px;
    }

    .website-card {
        min-height: 160px;
    }

    .website-icon {
        height: 40px;
    }

    .website-icon .el-image {
        width: 40px;
        height: 40px;
    }

    .website-info h3 {
        font-size: 14px;
    }

    .website-info p {
        font-size: 12px;
        -webkit-line-clamp: 2;
        height: 32px;
    }

    .mobile-fab {
        width: 48px;
        height: 48px;
        right: 16px;
        bottom: 65px;
    }
}
</style>
